<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
<script src="../resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>

<script>
description("Tests wrapping and unwrapping of AES-CBC keys using AES-KW and raw format");

jsTestIsAsync = true;

var kWrappingTestCases = [
  // AES-KW test vectors from http://www.ietf.org/rfc/rfc3394.txt
  // 4.1 Wrap 128 bits of Key Data with a 128-bit KEK
  {
    "wrappingKey": "000102030405060708090A0B0C0D0E0F",
    "key": "00112233445566778899AABBCCDDEEFF",
    "ciphertext": "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"
  },
  // 4.3 Wrap 128 bits of Key Data with a 256-bit KEK
  {
    "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
    "key": "00112233445566778899AABBCCDDEEFF",
    "ciphertext": "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7"
  },
  // 4.5 Wrap 192 bits of Key Data with a 256-bit KEK
  {
    "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
    "key": "00112233445566778899AABBCCDDEEFF0001020304050607",
    "ciphertext": "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1"
  },
  // 4.6 Wrap 256 bits of Key Data with a 256-bit KEK
  {
    "wrappingKey": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
    "key": "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F",
    "ciphertext": "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21"
  }
]

function runTestCase(testCase)
{
    var wrappingKey = null;
    var key = null;

    return Promise.resolve(null).then(function(result) {
        // Import the wrapping key
        var importAlgorithm = {name: 'aes-kw'};
        var keyData = hexStringToUint8Array(testCase.wrappingKey);
        var usages = ['wrapKey', 'unwrapKey'];
        var extractable = false;

        return crypto.subtle.importKey('raw', keyData, importAlgorithm, extractable, usages);
    }).then(function(result) {
        wrappingKey = result;

        // Import the key to be wrapped.
        var importAlgorithm = {name: 'HMAC', hash: {name: 'sha-1'}};
        var keyData = hexStringToUint8Array(testCase.key);
        var usages = ['sign', 'verify'];
        var extractable = true;

        return crypto.subtle.importKey('raw', keyData, importAlgorithm, extractable, usages);
    }).then(function(result) {
        key = result;

        // Wrap the key.
        var wrapAlgorithm = {name: 'aes-kw'};
        return crypto.subtle.wrapKey('raw', key, wrappingKey, wrapAlgorithm);
    }).then(function(result) {
        bytesShouldMatchHexString("Wrapped key data", testCase.ciphertext, result);

        // Unwrap the key.
        var wrappedKeyData = hexStringToUint8Array(testCase.ciphertext);
        var unwrapAlgorithm = {name: 'aes-kw'};
        var unwrappedKeyAlgorithm = {name: 'HMAC', hash: {name: 'sha-1'}};
        var extractable = true;
        var usages = ['sign'];
        return crypto.subtle.unwrapKey('raw', wrappedKeyData, wrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, usages);
    }).then(function(result) {
        unwrappedKey = result;

        shouldEvaluateAs("unwrappedKey.algorithm.name", "HMAC");
        shouldEvaluateAs("unwrappedKey.algorithm.hash.name", "SHA-1");
        shouldEvaluateAs("unwrappedKey.algorithm.length", testCase.key.length * 4);
        shouldEvaluateAs("unwrappedKey.extractable", true);
        shouldEvaluateAs("unwrappedKey.usages.join(',')", "sign");

        return crypto.subtle.exportKey('raw', unwrappedKey);
    }).then(function(result) {
        bytesShouldMatchHexString("Unwrapped key data", testCase.key, result);
    });
}

var lastPromise = Promise.resolve(null);

kWrappingTestCases.forEach(function(test) {
    lastPromise = lastPromise.then(runTestCase.bind(null, test));
});

lastPromise.then(finishJSTest, failAndFinishJSTest);

</script>

</body>
</html>
